package com.rainman.noswagger.info_bean;

import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.body.Parameter;
import com.rainman.noswagger.NoSwaggerCore;
import com.rainman.noswagger.core.BaseBean;
import com.rainman.noswagger.core.MethodTagWorkerInterface;
import lombok.Data;

import java.util.*;

@Data
public class MethodInfoBean extends BaseBean {

    private MethodDeclaration methodDeclaration;

    /**
     * 导包信息
     */
    private List<String> classImportsStrList;
    /**
     * 类包名
     */
    private String classPackageName;
    /**
     * 类名
     */
    private String className;
    /**
     * 类请求路径
     */
    private String classBaseUrl;

    /**
     * 请求路径
     */
    private List<String> urls;

    /**
     * 没有tag的注释
     */
    private String noTagCommentStr;
    /**
     * 解析后的单行注释
     */
    private List<String> lineCommentStr;
    /**
     * 解析后的单行@param注释
     */
    private List<String> lineParamCommentStr;

    /**
     * 解析后的单行@param注释Map方便使用
     */
    private HashMap<String,String> lineParamCommentStrMap;

    /**
     * 返回数据是否为集合
     */
    private Boolean returnDataArr=false;

    /**
     * 方法参数
     */
    private List<MethodParamInfoBean> paramBeanList;

    /**
     * 正确的返回数据
     */
    private List<BackInfoBean> returnBeanList;

    /**
     * 错误的返回数据
     */
    private List<ErrBackInfoBean> returnErrBeanList;


    public MethodInfoBean(MethodDeclaration methodDeclaration, ClassInfoBean classInfoBean, NoSwaggerCore core){
        super(methodDeclaration.getName().asString()
                ,core,methodDeclaration.getAnnotations(),methodDeclaration.getComment());

        this.methodDeclaration=methodDeclaration;

        urls=new ArrayList<>();
        lineCommentStr=new ArrayList<>();
        lineParamCommentStr=new ArrayList<>();
        lineParamCommentStrMap=new HashMap<>();
        paramBeanList=new ArrayList<>();
        returnBeanList=new ArrayList<>();
        returnErrBeanList=new ArrayList<>();

        this.classImportsStrList=classInfoBean.getImportsStrList();
        this.classPackageName=classInfoBean.getPackageName();
        this.className=classInfoBean.getName();
        this.classBaseUrl=classInfoBean.getBaseUrl();


        initData(classInfoBean);

    }

    private void initData(ClassInfoBean classInfoBean) {

        urls=getCore().getCoreConfig().getMethodInfoInterface().getUrls(this);

        if(urls.size()<=0){
            return;
        }
        initComment();

        buildParam(classInfoBean);


    }

    private void buildParam(ClassInfoBean classInfoBean) {
        NodeList<Parameter> parameters = methodDeclaration.getParameters();

        for(Parameter parameter:parameters){

            String typeName = matchImportsStr(parameter.getType().asString());//全类名
            ClassInfoBean classInfo =null;
            if(typeName.contains(".")){//匹配到了全类名
                 classInfo=getCore().getClassInfo(typeName);
            }

            paramBeanList.add(new MethodParamInfoBean(parameter,getCore()
                   ,typeName ,lineParamCommentStrMap.get(parameter.getNameAsString()),classInfo));
        }

    }

    private void initComment() {

        if(getOriCommentStr()==null){
            return;
        }

        String[] split = getOriCommentStr().split("\n");

        for(int ii=0;ii<split.length;ii++){
            String s=split[ii];
            if(s.trim().length()<=0){
                continue;
            }
            s = s.replaceFirst(" \\*", "");

            if(s.trim().startsWith("@")){

                    lineCommentStr.add(s.trim());

            }else {
                if(lineCommentStr.size()>0) {

                    if(s.trim().length()>0){
                        lineCommentStr.set(lineCommentStr.size() - 1, lineCommentStr.get(lineCommentStr.size() - 1) + "\n" + s.trim());
                    }

                }else {
                    noTagCommentStr=s;
                }
            }

        }

        dealCommentTag();
    }


    private void dealCommentTag() {

        for(String linStr:lineCommentStr){

            String[] forTag = linStr.split(" ");

            if("@param".equals(forTag[0])){
                String trim = linStr.length()==forTag[0].length()?"":linStr.substring(forTag[0].length()+1).trim();
                String[] forName = trim.split(" ");

                lineParamCommentStr.add(linStr);
                lineParamCommentStrMap.put(forName[0]
                        ,trim.length()==forName[0].length()?"":trim.substring(forName[0].length()+1));
                continue;
            }

            MethodTagWorkerInterface<?> methodTagWork = getCore().getCoreConfig().getMethodTagWork(forTag[0]);
            if(methodTagWork!=null){
                methodTagWork.dealTag(this
                        ,linStr.length()==forTag[0].length()?"":linStr.substring(forTag[0].length()+1),linStr);
            }

        }


    }

/*    public JSONObject getInfo(){

        JSONObject reJson=new JSONObject();
        reJson.set("classBaseUrl",classBaseUrl);
        reJson.set("urls",urls);
        reJson.set("name",getName());
        reJson.set("noTagCommentStr",noTagCommentStr);
        for (String key : getOtherInfo().keySet()) {
            reJson.set(key,getOtherInfo().get(key));
        }
        reJson.set("returnDataArr",returnDataArr);

        JSONArray paramInfo=new JSONArray();

        for(MethodParamInfoBean paramInfoBean:paramBeanList){
            paramInfo.add(paramInfoBean.getInfo());

        }

        reJson.set("paramInfo",paramInfo);

        JSONArray backInfo=new JSONArray();
        for(BackInfoBean backInfoBean:returnBeanList){
            backInfo.add(backInfoBean.getInfo());

        }
        reJson.set("backInfo",backInfo);

        JSONArray eBackInfo=new JSONArray();
        for(ErrBackInfoBean errBackInfoBean:returnErrBeanList){
            eBackInfo.add(errBackInfoBean.getInfo());
        }
        reJson.set("eBackInfo",eBackInfo);


        return reJson;
    }*/

    public String matchImportsStr(String typeName) {

        for(String im:classImportsStrList){
            if(im.endsWith("."+typeName)){
                return im;
            }

        }

        return typeName;
    }
}
